package com.harmonyos.cases.utils;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.harmonyos.cases.action.DemoTestAction;
import com.harmonyos.cases.constants.Constants;
import com.intellij.openapi.application.ApplicationManager;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.util.EntityUtils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

public class HttpRequest {
    public static volatile HttpRequest instance;
    private final CloseableHttpClient httpClient;
    private final PoolingHttpClientConnectionManager connectionManager;
    public static boolean isClosed = false;
    private int retryCount = 0;

    // 初始化httpclient
    public HttpRequest() {
        connectionManager = new PoolingHttpClientConnectionManager();
        // 设置最大连接数等参数
        connectionManager.setMaxTotal(100);
        connectionManager.setDefaultMaxPerRoute(10);

        // 获取系统代理设置
        String proxyHost = System.getProperty("http.proxyHost");
        String proxyPortStr = System.getProperty("http.proxyPort");
        Proxy proxy = null;
        if (proxyHost != null && proxyPortStr != null) {
            int proxyPort = Integer.parseInt(proxyPortStr);
            // 创建 Proxy 对象
            proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
        }

        RequestConfig.Builder requestConfigBuilder = RequestConfig.custom().setConnectTimeout(Constants.HTTP_CONNECT_TIMEOUT).setConnectionRequestTimeout(Constants.HTTP_CONNECT_TIMEOUT).setRedirectsEnabled(true);
        if (proxy != null) {
            HttpHost host = new HttpHost(proxyHost, Integer.parseInt(proxyPortStr));
            requestConfigBuilder.setProxy(host);
        }
        RequestConfig requestConfig = requestConfigBuilder.build();
        httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).setConnectionManager(connectionManager).build();
    }

    public static HttpRequest getInstance() {

        if (instance == null) {
            synchronized (HttpRequest.class) {
                if (instance == null) {
                    instance = new HttpRequest();
                    isClosed = false;
                }
            }
        } else {
            // 如果httpclient被关闭了并且没有中断下载，则重新创建httpclient
            if (isClosed) {
                if (DemoTestAction.canDownload) {
                    instance = new HttpRequest();
                    isClosed = false;
                }
            }
        }

        return instance;
    }

    // 取消下载
    public void cancel() {
        try {
            // 关闭httpclient
            httpClient.close();
            // 设置http状态为close
            isClosed = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 执行get请求
    public String executeGet(HttpGet httpGet) {
        String result = null;
        try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                result = EntityUtils.toString(entity);
            }
        } catch (Exception e) {
            e.printStackTrace();
//            throw new RuntimeException(e);
        }
        return result;
    }

    /**
     * 下载文件
     *
     * @param downloadPath 下载文件路径
     * @param localPath    本地存储路径
     * @param extra        下载需要的额外信息
     */
    public void download(String downloadPath, String localPath, String... extra) {
        HttpGet httpGet = new HttpGet(downloadPath);
        try (CloseableHttpResponse response = httpClient.execute(httpGet);) {
            HttpEntity entity = response.getEntity();
            if (entity != null) {
                // 如果httpclient未被关闭，则开始下载
                if (!isClosed) {
                    // 读取http返回流
                    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
                    byte[] data = new byte[1024];
                    int nRead;
                    while ((nRead = entity.getContent().read(data, 0, data.length)) != -1) {
                        buffer.write(data, 0, nRead);
                    }
                    buffer.flush();
                    byte[] bytes = buffer.toByteArray();
                    String content = new String(bytes, StandardCharsets.UTF_8);
                    // 异常处理，如果请求的文件返回的结果是Route error: Incorrect authorization result，则重新下载该文件，最多执行3次，防止卡死
                    // Route error: Incorrect authorization result是请求gitee文件原始数据时返回的错误信息，可能和网络有关，重复请求后可能会拿到正常的数据
                    if (content.endsWith("Route error: Incorrect authorization result")) {
                        Thread.sleep(1000);
                        retryCount++;
                        if (retryCount <= 3) {
                            download(downloadPath, localPath, extra);
                            return;
                        }
                    }
                    retryCount = 0;
                    // 如果是这几种文件，则直接处理数据后再写入文件，减少ide缓存影响
                    // 先写入文件再进行代码处理，可能导致ide缓存重复写入的问题
                    if (localPath.endsWith("hvigorfile.ts") || localPath.endsWith("Index.ets") || localPath.endsWith("oh-package.json5") || localPath.toLowerCase().endsWith("README.md".toLowerCase())) {
                        // 对文件内容进行处理
                        content = deleteCode(content, localPath, extra);
                        Files.writeString(Path.of(localPath), content);
                    } else {
                        // 其他类型的文件，直接下载到本地
                        Files.copy(new ByteArrayInputStream(bytes), Path.of(localPath), StandardCopyOption.REPLACE_EXISTING);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 删除文件中不必要的代码
    public String deleteCode(String content, String path, String... extra) {
        // 如果是hvigorfile.ts文件，则删除案例中自动生成动态路由插件的引用
        if (path.endsWith("hvigorfile.ts")) {
            String[] deleteList = {
                    "import { PluginConfig, etsGeneratorPlugin } from '@app/ets-generator';",
                    "etsGeneratorPlugin(config)",
                    "const config: PluginConfig = {\n" +
                            "    scanFiles: [\"src/main/ets/FeatureComponent\"],\n" +
                            "}",
                    "const config: PluginConfig = {\n" +
                            "  scanFiles: [\"src/main/ets/FeatureComponent\"],\n" +
                            "}"
            };
            content = delete(content, deleteList);
            return content;
        }
        // 如果是Index.ets文件，则将自动生成动态路由的export代码删除
        if (path.endsWith("Index.ets")) {
            content = delete(content, "export * from './src/main/ets/generated/RouterBuilder';");
            return content;
        }
        // 如果是oh-package.json5文件，则移除动态路由、base的依赖
        if (path.endsWith("oh-package.json5")) {
            content = Json5Parser.parseJson5(content);
            JsonObject jsonObject = JsonParser.parseString(content).getAsJsonObject();
            if (jsonObject.has("dependencies")) {
                JsonObject dependenciesObject = jsonObject.get("dependencies").getAsJsonObject();
                dependenciesObject.remove("@ohos/dynamicsrouter");
                dependenciesObject.remove("@ohos/dynamicsRouter");
                dependenciesObject.remove("@ohos/base");
                dependenciesObject.remove("utils");
                dependenciesObject.remove("routermodule");
            }
            try {
                ObjectMapper objectMapper = new ObjectMapper();
                // 直接将json进行格式化。如果使用ide的格式化方法，可能导致缓存问题，无法正常写入文件
                content = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(objectMapper.readValue(jsonObject.toString(), Object.class));
            } catch (JsonProcessingException ignore) {
                ignore.printStackTrace();
            }
            return content;
        }

        // 如果是readme文件，则下载gif图片，并替换gif路径
        // 不能直接使用在线gif路径，部分md解析器无法识别图片，包括DevEco
        if (path.toLowerCase().endsWith("README.md".toLowerCase())) {
            if (extra != null && extra.length > 0) {
                String gifPath = extra[0];
                if (gifPath != null && !gifPath.isEmpty()) {
                    String gifName = InsertUtils.getFileNameFromUrl(gifPath);
                    String needReplaceStr = "../../product/entry/src/main/resources/base/media/" + gifName;

                    String gifLocalPath = path.substring(0, path.lastIndexOf("/") + 1) + gifName;
                    download(gifPath, gifLocalPath);
                    while (content.contains(needReplaceStr)) {
                        content = content.replace(needReplaceStr, gifName);
                    }
                    return content;
                }
            }
        }
        return content;
    }

    // 删除string中的不必要代码
    private String delete(String content, String... replaces) {
        if (replaces != null) {
            for (String replace : replaces) {
                content = content.replace(replace, "");
            }
        }
        while (content.contains("\n\n\n")) {
            content = content.replace("\n\n\n", "");
        }
        return content;
    }
}
